package com.jgp.security.service;

import com.jgp.common.pojo.TreeBean;
import com.jgp.security.secmodel.SecInstitution;
import com.jgp.security.secrepository.SecInstitutionRepository;
import com.jgp.sys.query.Operator;
import com.jgp.sys.query.OrderDirection;
import com.jgp.sys.query.OrderList;
import com.jgp.sys.query.QueryFilterList;
import com.jgp.sys.ui.Pager;
import com.jgp.sys.utils.TreeUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目   jgp-cloud-parent
 * 作者   loufei
 * 时间   2019-11-03
 */
@Log4j2
@Service
@CacheConfig(cacheNames = "INSTITUTION-SERVICE")
@Transactional(transactionManager = "secondTransactionManager", readOnly = true)
public class SecInstitutionService {
    
    @Lazy
    @Autowired
    private SecInstitutionRepository repository;
    
    /**
     * 【缓存】
     * 缓存整个菜单树
     *
     * @return
     */
    @Cacheable(key = "'TREE:'+#clientId+':full'")
    public List<TreeBean> queryFullTreeFromCache(String clientId) {
        return queryFullTree();
    }
    
    @Cacheable(key = "'MAP:'+#clientId+':full'")
    public Map<Long,SecInstitution> queryFullMap(String clientId) {
        List<SecInstitution> institutions = query(null, null);
        return institutions.stream().collect(Collectors.toMap(SecInstitution::getId,treeBean -> treeBean));
    }
    
    /**
     * 【缓存】
     * 清除缓存
     */
    @Caching(evict = {
            @CacheEvict(key = "'TREE:'+#clientId+':*'", allEntries = true),
            @CacheEvict(key = "'MAP:'+#clientId+':*'", allEntries = true)
    })
    public void removeCache(String clientId) { }
    
    /**
     * 创建/更新组织机构
     *
     * @param institution
     * @return
     */
    @Transactional(transactionManager = "secondTransactionManager")
    public SecInstitution save(SecInstitution institution) {
        return repository.createOrUpdate(institution);
    }
    
    /**
     * 查询整个树
     *
     * @return
     */
    public List<TreeBean> queryFullTree() {
        return TreeUtil.createTree(query(null, null));
    }
    
    /**
     * 根据条件查询菜单项
     *
     * @param parentId 父级ID【EQ】
     * @param name     标题【LIKE】
     * @return
     */
    public List<SecInstitution> query(Long parentId, String name) {
        return query(parentId, name, null);
    }
    
    
    /**
     * 【分页】
     * 根据条件查询菜单项
     *
     * @param parentId 父级ID【EQ】
     * @param name     标题【LIKE】
     * @param pager    分页
     * @return
     */
    public List<SecInstitution> query(Long parentId, String name, Pager pager) {
        QueryFilterList filters = filters(parentId, name);
        OrderList orders = new OrderList();
        orders.addOrder("sort", "ASC");
        return repository.read(filters, orders, pager);
    }
    
    public SecInstitution queryOne(Long id) {
        return repository.read(id);
    }
    
    /**
     * 查询子节点
     *
     * @param parentId
     * @return
     */
    public List<TreeBean> queryTreeLazy(Long parentId) {
        return TreeUtil.createTree(query(parentId, null));
    }
    
    @Transactional(transactionManager = "secondTransactionManager")
    public void removeInstitution(List<Long> ids) {
        QueryFilterList filters = new QueryFilterList();
        filters.addFilter("id", Operator.in, ids);
        repository.deleteTreeItemAndAllChildren(filters);
    }
    
    @Transactional(transactionManager = "secondTransactionManager")
    public void removeInstitution(Long id) {
        QueryFilterList filters = new QueryFilterList();
        filters.addFilter("id", Operator.eq, id);
        repository.deleteTreeItemAndAllChildren(filters);
    }
    
    
    /**
     * 构建条件过滤器
     *
     * @param parentId
     * @param name
     * @return
     */
    private QueryFilterList filters(Long parentId, String name) {
        QueryFilterList filters = new QueryFilterList();
        if (StringUtils.isNotBlank(name)) filters.addFilter("name", Operator.like, name);
        if (Objects.nonNull(parentId)) {
            filters.addFilter("parentId", Operator.eq, parentId);
        }
        return filters;
    }
    
    @Cacheable(keyGenerator = "listKeyGenerator")
    public List<SecInstitution> queryDown(List<SecInstitution> institutions) {
        List<SecInstitution> result = new ArrayList<>();
        institutions.forEach(institution -> {
            QueryFilterList filters = new QueryFilterList();
            filters.addFilter("supers", Operator.likeL, institution.getSupers() + "," + institution.getId());
            List<SecInstitution> list = repository.read(filters);
            result.addAll(list);
        });
        return result;
    }
    
    /**
     * 查询制定机构的父级是否有特殊单位，包括本身
     *
     * @param institutions
     * @return
     */
    public List<SecInstitution> querySpecialInstitutions(List<SecInstitution> institutions) {
        Set<Long> ids = new HashSet<>();
        institutions.forEach(institution -> {
            List<String> tops = Arrays.asList(StringUtils.split(institution.getSupers(), ","));
            List<SecInstitution> topsIns = repository.read(tops.stream().map(Long::valueOf).collect(Collectors.toList()));
            topsIns.add(institution);
            List<SecInstitution> sorted = topsIns.stream().filter(ins -> StringUtils.isNotBlank(ins.getSpecialTypeCode()))
                   .sorted(Comparator.comparing(ins -> ins.getSupers().split(",").length)).collect(Collectors.toList());
            if(Objects.nonNull(sorted)&&sorted.size()>0){
                ids.add(sorted.get(sorted.size()-1).getId());
            }
        });
        List<SecInstitution> specials = repository.read(ids);
        /*nodes.addAll(institutions);
        List<SecInstitution> specials = new ArrayList<>();
        nodes.forEach(institution -> {
            if (StringUtils.isNotBlank(institution.getSpecialTypeCode())) {
                specials.add(institution);
            }
        });*/
        return specials;
    }
    
    /**
     * 查询特殊机构
     *
     * @param specialCode
     * @return
     */
    public List<SecInstitution> queryInstitutionsBySpecialCode(String specialCode) {
        QueryFilterList filters = new QueryFilterList();
        filters.addFilter("specialTypeCode", Operator.eq, specialCode);
        
        OrderList orders = new OrderList();
        orders.addOrder("sort", OrderDirection.ASC);
        
        return repository.read(filters, orders);
    }
    
    /**
     * @param filters
     * @param orders
     * @param pager
     * @return
     */
    public List<SecInstitution> query(QueryFilterList filters, OrderList orders, Pager pager) {
        return repository.read(filters, orders, pager);
    }
    
    public List<SecInstitution> queryTop() {
        QueryFilterList filters = new QueryFilterList();
        filters.addFilter("parentId", Operator.eq, -1);
        return repository.read(filters);
    }
    
    public List<SecInstitution> queryInstitutions(Set<Long> orgIds) {
        return repository.read(orgIds);
    }
}
